How it works
- On page load, call
GET /v1/{brand}/optionsto get the two customer questions (labels + dropdown values). - With the customer’s answers plus the structure’s delivery ZIP and total price, call
POST /v1/{brand}/estimate. - Show what comes back. Eligibility, terms, payments, APRs, Apply links and disclosure text are all pre-computed.
https://payment-estimate-api.pages.dev · Brand: stoltzfus (more brands coming)JSON in, JSON out, no API key. Browser calls are allowed from
mysheds.com (any subdomain) and localhost. Calls from your server (no Origin header) are always allowed. Need another domain allowed, e.g. a staging site? Ask Tim Brazil.
shedlender.com/estimator.html), so your widget can never disagree with it. If our estimator’s calculation logic changes, the API returns HTTP 503 estimates_unavailable until we confirm the change. Please handle that by hiding the payment section or showing a short “unavailable” note.
Your widget, your layout
You decide when to call the API and how to show the results. No button is required. The test page lets you try three styles:
- A · Automatic: call
/estimatewhenever an input or the price changes, and show the payments without a button. - B · Term dropdown: show one payment and let the customer switch terms from a dropdown (start on
loans.defaultTermYears). - C · Button + tiles: the customer presses a button, then picks a term tile.
For automatic updates, only call the API once the ZIP has 5 digits, price is above 0 and both questions are answered. Wait about 0.4 seconds after the last keystroke, and ignore any older response that comes back after a newer one. That keeps it fast and well under the limit of 120 rent-to-own quotes per visitor every 10 minutes. Switching terms needs no new call, because every term is already in the response.
1 · GET /v1/stoltzfus/options
Build your two <select>s from questions.creditScore.options and questions.ownProperty.options, then send the value back.
{
"questions": {
"creditScore": { "label": "What is your credit score?", "placeholder": "— Select credit score —",
"options": [ { "value": "840", "label": "840 – 850" }, … { "value": "500", "label": "Below 550" } ] },
"ownProperty": { "label": "Do you own the property where the project is located?",
"options": [ { "value": "own", "label": "Yes, I own the property" },
{ "value": "biz", "label": "Yes, my business owns the property" },
{ "value": "no", "label": "No, I do not own the property" } ] }
},
"lenders": { "upgrade": { "minCreditScore": 680, "minAmount": 2000, "maxAmount": 100000, … }, "thrive": { … }, "rto": { … } },
"disclosures": { … }, "displayRules": [ … ]
}
2 · POST /v1/stoltzfus/estimate
| Field | Type | Example | Notes |
|---|---|---|---|
zip | string | "19310" | Delivery ZIP. Sets sales tax and state availability for rent-to-own. |
price | number | 16820 | Total price of the structure with options, in dollars. |
creditScore | string | "720" | A value from /options. |
ownProperty | string | "own" | A value from /options (own · biz · no). |
GET /v1/stoltzfus/estimate?zip=19310&price=16820&creditScore=720&ownProperty=own also works, which is handy for testing in a browser tab.
const res = await fetch('https://payment-estimate-api.pages.dev/v1/stoltzfus/estimate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ zip: '19310', price: 16820, creditScore: '720', ownProperty: 'own' })
});
if (res.status === 503) { /* hide the payment section — estimates temporarily off */ }
const data = await res.json();
Response (shortened)
{
"ok": true,
"input": { "zip": "19310", "state": "PA", "price": 16820, "creditScore": "720", "ownProperty": "own" },
"loans": {
"available": true,
"defaultTermYears": 20, // pre-select this term (the longest)
"terms": [ // ONE payment per term — use these for your payment choices
{ "years": 5, "label": "5-Year", "monthlyPaymentDisplay": "$372", "aprDisplay": "7.99% APR*", "footnote": "†",
"paymentNote": "Months 1–6 are interest-only; …", "bestLender": "thrive",
"offers": [ { "lenderName": "Thrive Financial", "monthlyPaymentDisplay": "$372", "aprDisplay": "7.99% APR*", "applyLink": "…" },
{ "lenderName": "Upgrade", "monthlyPaymentDisplay": "$349", "aprDisplay": "8.99% APR*", "applyLink": "…" } ] },
…
{ "years": 20, "label": "20-Year", "monthlyPaymentDisplay": "$164", "aprDisplay": "9.99% APR*", "footnote": "†", "offers": [ … Thrive only … ] }
],
"byLender": { // full per-lender detail, exactly as the estimator shows it
"upgrade": { "eligible": true, "terms": [ 5, 7, 10, 12, 15-year … ] },
"thrive": { "eligible": true, "terms": [ … incl. interestOnlyPayments for months 1–6 … ] }
},
"message": null // text to show when available = false
},
"rentToOwn": {
"available": true, "creditCheck": false, "defaultTermMonths": 48,
"terms": [ { "months": 24, "monthlyPaymentDisplay": "$1,048.77", "upfrontPayment": 3364 }, … ],
"overMaxText": null, // set when the price is over $25,000 (payments are for $25,000)
"notes": [ "Rent-to-own is not available for 2-story structures or …" ],
"applyLink": "https://payment-estimate-api.pages.dev/v1/stoltzfus/apply/rto",
"reason": null, "reasonText": null // why it’s unavailable, when available = false
},
"disclosures": {
"forThisWidget": [ // show ALL of these, in order — word-for-word from our estimator
{ "type": "paragraph", "paragraphs": [ { "text": "Stoltzfus Structures is not a lender…", "html": "…" } ] },
{ "type": "heading", "text": "Important Disclosures" },
{ "type": "section", "id": "disc-rto", "title": "Rent-to-Own (SmartPay)",
"paragraphs": [ { "text": "You do not own the structure until…", "html": "… higher than the cash price …" } ] },
…
],
"all": [ … ], // the estimator's whole footer, incl. products this widget doesn't offer
"representativeExample": "…", "rentToOwnStructures": "Structures that are 2 stories or … do not qualify for rent-to-own."
},
"displayRules": [ … ]
}
Errors return HTTP 400 with {"ok":false,"error":"invalid_input","fields":{"zip":"Enter a valid 5-digit US ZIP code"}}. The messages are written for customers, so you can show them as-is.
Display rules (please follow)
- Always show a loan payment together with its APR and term. Never show a payment by itself.
- Keep the * on APRs and the † on interest-only terms, and put the matching disclosures on the page.
- Don’t name the lender on the payment choices. Show lender names only at the Apply step (
terms[].offers). - No APR or interest rate for rent-to-own. It’s a lease, not a loan.
- When a result has
overMaxText, show it next to those payments. - Disclosures: render every block in
disclosures.forThisWidget, in order. Usehtmlto keep the bold text. They are copied word-for-word from our estimator and update automatically when we change them, so please don’t retype or edit them. - Show each lender’s
applyHint(the small print under our Apply buttons) next to its Apply button. - Don’t call any of these products “unsecured”.
Do / don’t (what compliant looks like)
✓ Do
Payment always with its APR and term, markers kept.
✗ Don’t
A payment on its own (no APR, no term) breaks federal advertising rules.
✓ Do
Rent-to-own shows cost only. It’s a lease, not a loan.
✗ Don’t
Never show an APR or interest rate for rent-to-own.
✓ Do
Lender names appear only at the Apply step.
✗ Don’t
Don’t brand the payment choices with lender names.
✓ Do
Show loans.notice / overMaxText next to capped payments.
✗ Don’t
Hiding the cap makes the payment look like it covers the full price.
✓ Do
disclosures.forThisWidget, word-for-word, in orderThey update automatically when our estimator changes.
✗ Don’t
Don’t paraphrase, shorten or hard-code the disclosures.
Errors and “not available” reasons
| What comes back | When | What the customer should see | Try it |
|---|---|---|---|
HTTP 503 estimates_unavailable | Safety switch: our estimator’s calculation logic changed and we haven’t confirmed it yet | Hide the payment section, or “Payment estimates are temporarily unavailable.” | ?simulate=unavailable |
HTTP 400 invalid_input + fields | Bad ZIP, price, or answer value | Each field message under its input (written for customers) | ?simulate=invalid |
HTTP 403 origin_not_allowed | Called from a website not on our list | Customers never see this on mysheds.com. Ask Tim to add a new staging address. (The browser shows it as a CORS error.) | ?simulate=origin_blocked |
rentToOwn.reason: quote_unavailable | SmartPay’s quote service didn’t answer | rentToOwn.reasonText, and keep the SmartPay Apply button | ?simulate=rto_unavailable |
| Slow answer | Network or SmartPay slow | A loading state. Never block the page | ?simulate=slow (4 s) |
loans.available: false + loans.message | No loan fits (e.g. credit below 550) | loans.message (rent-to-own may still show) | credit 500 |
loans.notice | Price is over every lender’s max; payments are for the capped amount | The notice, right beside the payments | price 300000 |
byLender.*.reason | credit_score · amount_below_minimum · state · property_ownership · coming_soon | Optional: reasonText if you show why a lender isn’t offered | own no, credit 640 |
rentToOwn.reason | state (AK HI MN MS WA WI WY) · amount_below_minimum (<$1,000) · zip_not_supported | rentToOwn.reasonText, or hide rent-to-own | ZIP 53703 |
Every error is JSON {"ok":false,"error":…}. The simulator values work on /estimate as a query parameter or a "simulate" field in the POST body, and are never counted in usage stats.
Developer kit
Everything is ready to use. Copy the three widget files into the Next.js project, or build your own UI from the types.
getOptions() and getEstimate() helpers. Type-checked against live responses.
monthly-payment-estimate.css.pme-* classes and --pme-* variables (mysheds colors and Rubik). Restyle freely.
README.mdInstall, props, examples for each style, error handling.
openapi.jsonOpenAPI 3.0 description of the whole API. Import into Swagger, Postman or a code generator.
Postman collection22 ready-made requests including every error simulation, with tests.
Download everything (.zip)All of the above in one file.
Launch checklist
- Open the test page, press Run all scenarios, and confirm all pass.
- Add the widget to a garage page on staging or localhost (
localhostis already allowed). Send Tim any other staging address to allow. - Feed it the total price from your price calculator, including options. Don’t call the API for custom-quote structures (Build On-Site, Attached); show “request a quote”.
- Check each widget style you use with the test page’s Error simulator: 503, 400 and rent-to-own down.
- Confirm Apply buttons use
applyLinkand open in a new tab only whenapplyOpensNewTabis true. - Confirm the disclosures from
disclosures.forThisWidgetappear on the page, word for word. - Phone check: the widget fits a 360-pixel-wide screen.
- Send Tim the staging link for a compliance look before going live.
- Go live. Tim gets an automatic email if our rules change or estimates switch off, and so do you once you’re on the alert list.
Usage stats and alerts
The API keeps anonymous counts only (estimates shown, Apply clicks per lender, per day). It never stores customer answers, ZIPs or prices. Apply clicks are counted when buttons use applyLink, which forwards the customer to the lender. A monitor checks every hour and emails if our estimator’s rates, rules or disclosures change (the API already follows them, so your widget needs no change) or if estimates switch off.
Field reference
Show every response field (generated from openapi.json)
| Field (POST /estimate response) | Type | What it means |
|---|---|---|
ok | boolean | Always `true` on a successful response. |
apiVersion | string | API version (a date). |
brand | string | Brand slug. |
rulesFrom | object | Where and when the API read the rules it used for this response. |
rulesFrom.estimator | string | The published estimator page the rules were read from. |
rulesFrom.estimatorVersion | string | Short hash of the estimator version the rules came from. Changes whenever the estimator page changes. |
rulesFrom.readAt | string | When the rules were read from the estimator (UTC, ISO 8601). |
rulesFrom.source | string | How the rules were obtained for this response, e.g. `live` (just read from the estimator page) or `cache` (a recent read is being reused). |
input | object | The inputs the estimate was calculated for. |
input.zip | string | ZIP as received (5 digits). |
input.state | string or null | Two-letter state for the ZIP, or null when the ZIP is not in one of the 50 states or DC (e.g. Puerto Rico). |
input.price | number | Price as received (USD). |
input.creditScore | string | Credit-score value as received. |
input.creditScoreLabel | string | Its label. |
input.ownProperty | string | Ownership value as received. |
input.ownPropertyLabel | string | Its label. |
loans | object | Loan payments (Upgrade and Thrive Financial). |
loans.available | boolean | True when at least one loan term is offered. |
loans.defaultTermYears | integer or null | Term (years) to pre-select — the longest offered. Null when no loans. |
loans.terms | list of object | ONE payment choice per term, shortest first. Use these for your payment choices. Empty when `available` is false. |
loans.terms[].lender | string | Loan lender key. |
loans.terms[].years | integer | Term in years. |
loans.terms[].months | integer | Term in months. |
loans.terms[].label | string | Term label for your UI, e.g. `5-Year`, or `12-Year Offer` for a Thrive counter-offer term. |
loans.terms[].amount | number | Amount (USD) the payment is calculated on. Lower than the price when the price is over this lender's maximum. |
loans.terms[].apr | number | APR as a percent number (7.99 = 7.99%). |
loans.terms[].aprDisplay | string | APR ready to show, including the `*` marker — keep it exactly as given. |
loans.terms[].monthlyPayment | number | Monthly payment (USD, unrounded to the cent). |
loans.terms[].monthlyPaymentDisplay | string | Monthly payment ready to show. Always show it together with `aprDisplay` and the term. |
loans.terms[].interestOnly | boolean | True when the first months are interest-only (Thrive Building Loan). |
loans.terms[].footnote | string | `†` on interest-only terms, otherwise an empty string. Keep it next to the payment. |
loans.terms[].paymentNote | string | One-line explanation of the payment to show near it. |
loans.terms[].estimatorLabel | string | Thrive rows only: the label the estimator itself uses, e.g. `5-Year Term`, `12-Year Offer`. |
loans.terms[].counterOffer | boolean | Thrive rows only: true for a counter-offer term (offered to some credit tiers instead of the standard term). |
loans.terms[].interestOnlyMonths | integer | Thrive rows only: number of interest-only months at the start. |
loans.terms[].interestOnlyPayments | object | Thrive Building Loan: what months 1–6 (interest-only) cost. |
loans.terms[].interestOnlyPayments.halfReleased | number | Interest-only payment (USD) while half of the loan has been released. |
loans.terms[].interestOnlyPayments.halfReleasedDisplay | string | Formatted, e.g. `$56/mo`. |
loans.terms[].interestOnlyPayments.fullReleased | number | Interest-only payment (USD) once the full loan has been released. |
loans.terms[].interestOnlyPayments.fullReleasedDisplay | string | Formatted, e.g. `$112/mo`. |
loans.terms[].bestLender | string | Key of the lender whose numbers this row shows (observed: the lowest APR for the term). Do not show the lender name on this row. |
loans.terms[].offers | list of object | Every lender offering this term (1 or more) — show these, with lender names, at the Apply step. |
loans.terms[].offers[].lender | string | Loan lender key. |
loans.terms[].offers[].years | integer | Term in years. |
loans.terms[].offers[].months | integer | Term in months. |
loans.terms[].offers[].label | string | Term label for your UI, e.g. `5-Year`, or `12-Year Offer` for a Thrive counter-offer term. |
loans.terms[].offers[].amount | number | Amount (USD) the payment is calculated on. Lower than the price when the price is over this lender's maximum. |
loans.terms[].offers[].apr | number | APR as a percent number (7.99 = 7.99%). |
loans.terms[].offers[].aprDisplay | string | APR ready to show, including the `*` marker — keep it exactly as given. |
loans.terms[].offers[].monthlyPayment | number | Monthly payment (USD, unrounded to the cent). |
loans.terms[].offers[].monthlyPaymentDisplay | string | Monthly payment ready to show. Always show it together with `aprDisplay` and the term. |
loans.terms[].offers[].interestOnly | boolean | True when the first months are interest-only (Thrive Building Loan). |
loans.terms[].offers[].footnote | string | `†` on interest-only terms, otherwise an empty string. Keep it next to the payment. |
loans.terms[].offers[].paymentNote | string | One-line explanation of the payment to show near it. |
loans.terms[].offers[].estimatorLabel | string | Thrive rows only: the label the estimator itself uses, e.g. `5-Year Term`, `12-Year Offer`. |
loans.terms[].offers[].counterOffer | boolean | Thrive rows only: true for a counter-offer term (offered to some credit tiers instead of the standard term). |
loans.terms[].offers[].interestOnlyMonths | integer | Thrive rows only: number of interest-only months at the start. |
loans.terms[].offers[].interestOnlyPayments | object | Thrive Building Loan: what months 1–6 (interest-only) cost. |
loans.terms[].offers[].interestOnlyPayments.halfReleased | number | Interest-only payment (USD) while half of the loan has been released. |
loans.terms[].offers[].interestOnlyPayments.halfReleasedDisplay | string | Formatted, e.g. `$56/mo`. |
loans.terms[].offers[].interestOnlyPayments.fullReleased | number | Interest-only payment (USD) once the full loan has been released. |
loans.terms[].offers[].interestOnlyPayments.fullReleasedDisplay | string | Formatted, e.g. `$112/mo`. |
loans.terms[].offers[].lenderName | string | Lender display name — show it here, at the Apply step. |
loans.terms[].offers[].product | string | Product name. |
loans.terms[].offers[].applyUrl | string | The lender's own application page (reference only). |
loans.terms[].offers[].applyLink | string | Point the Apply button here. It counts the click anonymously, then redirects to the lender. Carries `?term=<months>`. |
loans.terms[].offers[].applyOpensNewTab | boolean | Open `applyLink` in a new tab when true. |
loans.terms[].offers[].applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
loans.terms[].offers[].applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
loans.terms[].offers[].applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
loans.byLender | object | Per-lender detail (eligibility, reasons, every term). |
loans.byLender.upgrade | object | Full detail for one loan lender. |
loans.byLender.upgrade.lender | string | Lender display name. |
loans.byLender.upgrade.product | string | Product name. |
loans.byLender.upgrade.eligible | boolean | Whether this lender can offer these answers. |
loans.byLender.upgrade.comingSoon | boolean | True when the program is announced but not yet open. |
loans.byLender.upgrade.reason | string or null | Why not eligible, as a code — e.g. `credit_score`, `property_ownership`, `amount_below_minimum`, `state`. Null when eligible. |
loans.byLender.upgrade.reasonText | string or null | Why not eligible, in customer-ready words. Null when eligible. |
loans.byLender.upgrade.applyUrl | string | The lender's own application page (reference only). |
loans.byLender.upgrade.applyLink | string | Apply link (counts the click anonymously, then redirects). |
loans.byLender.upgrade.applyOpensNewTab | boolean | Open `applyLink` in a new tab when true. |
loans.byLender.upgrade.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
loans.byLender.upgrade.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
loans.byLender.upgrade.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
loans.byLender.upgrade.terms | list of object | This lender's own term rows, exactly as the estimator shows them. Empty when not eligible. |
loans.byLender.upgrade.terms[].lender | string | Loan lender key. |
loans.byLender.upgrade.terms[].years | integer | Term in years. |
loans.byLender.upgrade.terms[].months | integer | Term in months. |
loans.byLender.upgrade.terms[].label | string | Term label for your UI, e.g. `5-Year`, or `12-Year Offer` for a Thrive counter-offer term. |
loans.byLender.upgrade.terms[].amount | number | Amount (USD) the payment is calculated on. Lower than the price when the price is over this lender's maximum. |
loans.byLender.upgrade.terms[].apr | number | APR as a percent number (7.99 = 7.99%). |
loans.byLender.upgrade.terms[].aprDisplay | string | APR ready to show, including the `*` marker — keep it exactly as given. |
loans.byLender.upgrade.terms[].monthlyPayment | number | Monthly payment (USD, unrounded to the cent). |
loans.byLender.upgrade.terms[].monthlyPaymentDisplay | string | Monthly payment ready to show. Always show it together with `aprDisplay` and the term. |
loans.byLender.upgrade.terms[].interestOnly | boolean | True when the first months are interest-only (Thrive Building Loan). |
loans.byLender.upgrade.terms[].footnote | string | `†` on interest-only terms, otherwise an empty string. Keep it next to the payment. |
loans.byLender.upgrade.terms[].paymentNote | string | One-line explanation of the payment to show near it. |
loans.byLender.upgrade.terms[].estimatorLabel | string | Thrive rows only: the label the estimator itself uses, e.g. `5-Year Term`, `12-Year Offer`. |
loans.byLender.upgrade.terms[].counterOffer | boolean | Thrive rows only: true for a counter-offer term (offered to some credit tiers instead of the standard term). |
loans.byLender.upgrade.terms[].interestOnlyMonths | integer | Thrive rows only: number of interest-only months at the start. |
loans.byLender.upgrade.terms[].interestOnlyPayments | object | Thrive Building Loan: what months 1–6 (interest-only) cost. |
loans.byLender.upgrade.terms[].interestOnlyPayments.halfReleased | number | Interest-only payment (USD) while half of the loan has been released. |
loans.byLender.upgrade.terms[].interestOnlyPayments.halfReleasedDisplay | string | Formatted, e.g. `$56/mo`. |
loans.byLender.upgrade.terms[].interestOnlyPayments.fullReleased | number | Interest-only payment (USD) once the full loan has been released. |
loans.byLender.upgrade.terms[].interestOnlyPayments.fullReleasedDisplay | string | Formatted, e.g. `$112/mo`. |
loans.byLender.upgrade.overMax | boolean | True when the price is over this lender's maximum (payments are for the maximum). |
loans.byLender.upgrade.overMaxText | string or null | Customer-ready note to show beside this lender's payments when `overMax` is true; otherwise null. |
loans.byLender.thrive | object | Full detail for one loan lender. |
loans.byLender.thrive.lender | string | Lender display name. |
loans.byLender.thrive.product | string | Product name. |
loans.byLender.thrive.eligible | boolean | Whether this lender can offer these answers. |
loans.byLender.thrive.comingSoon | boolean | True when the program is announced but not yet open. |
loans.byLender.thrive.reason | string or null | Why not eligible, as a code — e.g. `credit_score`, `property_ownership`, `amount_below_minimum`, `state`. Null when eligible. |
loans.byLender.thrive.reasonText | string or null | Why not eligible, in customer-ready words. Null when eligible. |
loans.byLender.thrive.applyUrl | string | The lender's own application page (reference only). |
loans.byLender.thrive.applyLink | string | Apply link (counts the click anonymously, then redirects). |
loans.byLender.thrive.applyOpensNewTab | boolean | Open `applyLink` in a new tab when true. |
loans.byLender.thrive.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
loans.byLender.thrive.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
loans.byLender.thrive.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
loans.byLender.thrive.terms | list of object | This lender's own term rows, exactly as the estimator shows them. Empty when not eligible. |
loans.byLender.thrive.terms[].lender | string | Loan lender key. |
loans.byLender.thrive.terms[].years | integer | Term in years. |
loans.byLender.thrive.terms[].months | integer | Term in months. |
loans.byLender.thrive.terms[].label | string | Term label for your UI, e.g. `5-Year`, or `12-Year Offer` for a Thrive counter-offer term. |
loans.byLender.thrive.terms[].amount | number | Amount (USD) the payment is calculated on. Lower than the price when the price is over this lender's maximum. |
loans.byLender.thrive.terms[].apr | number | APR as a percent number (7.99 = 7.99%). |
loans.byLender.thrive.terms[].aprDisplay | string | APR ready to show, including the `*` marker — keep it exactly as given. |
loans.byLender.thrive.terms[].monthlyPayment | number | Monthly payment (USD, unrounded to the cent). |
loans.byLender.thrive.terms[].monthlyPaymentDisplay | string | Monthly payment ready to show. Always show it together with `aprDisplay` and the term. |
loans.byLender.thrive.terms[].interestOnly | boolean | True when the first months are interest-only (Thrive Building Loan). |
loans.byLender.thrive.terms[].footnote | string | `†` on interest-only terms, otherwise an empty string. Keep it next to the payment. |
loans.byLender.thrive.terms[].paymentNote | string | One-line explanation of the payment to show near it. |
loans.byLender.thrive.terms[].estimatorLabel | string | Thrive rows only: the label the estimator itself uses, e.g. `5-Year Term`, `12-Year Offer`. |
loans.byLender.thrive.terms[].counterOffer | boolean | Thrive rows only: true for a counter-offer term (offered to some credit tiers instead of the standard term). |
loans.byLender.thrive.terms[].interestOnlyMonths | integer | Thrive rows only: number of interest-only months at the start. |
loans.byLender.thrive.terms[].interestOnlyPayments | object | Thrive Building Loan: what months 1–6 (interest-only) cost. |
loans.byLender.thrive.terms[].interestOnlyPayments.halfReleased | number | Interest-only payment (USD) while half of the loan has been released. |
loans.byLender.thrive.terms[].interestOnlyPayments.halfReleasedDisplay | string | Formatted, e.g. `$56/mo`. |
loans.byLender.thrive.terms[].interestOnlyPayments.fullReleased | number | Interest-only payment (USD) once the full loan has been released. |
loans.byLender.thrive.terms[].interestOnlyPayments.fullReleasedDisplay | string | Formatted, e.g. `$112/mo`. |
loans.byLender.thrive.overMax | boolean | True when the price is over this lender's maximum (payments are for the maximum). |
loans.byLender.thrive.overMaxText | string or null | Customer-ready note to show beside this lender's payments when `overMax` is true; otherwise null. |
loans.message | string or null | Text to show instead of loan payments when `available` is false; null otherwise. |
loans.notice | string or null | Note to show beside the loan payments (e.g. the price is over the maximum of the lender whose numbers are shown). Null when there is nothing to say. |
rentToOwn | object | Rent-to-own (SmartPay). A lease, not a loan: never show an APR or interest rate for it. |
rentToOwn.available | boolean | True when rent-to-own payments are shown (`terms` is filled). |
rentToOwn.eligible | boolean | Whether these answers qualify for rent-to-own. Can be true while `available` is false (e.g. the live quote failed — the customer can still apply). |
rentToOwn.provider | string | Provider name — show only at the Apply step. |
rentToOwn.product | string | Product name. |
rentToOwn.creditCheck | boolean | False: rent-to-own uses no credit check. |
rentToOwn.amount | number or null | Amount (USD) the payments are for (capped at the rent-to-own maximum). Null when not eligible. |
rentToOwn.defaultTermMonths | integer or null | Term (months) to pre-select. Null when unavailable. |
rentToOwn.terms | list of object | Lease terms. Empty when `available` is false. |
rentToOwn.terms[].months | integer | Lease term in months. |
rentToOwn.terms[].label | string | Term label. |
rentToOwn.terms[].monthlyPayment | number | Monthly lease payment (USD), tax included. |
rentToOwn.terms[].monthlyPaymentDisplay | string | Monthly payment ready to show (to the cent). Never pair it with an APR or rate — it is a lease. |
rentToOwn.terms[].upfrontPayment | number | Amount due upfront (USD). |
rentToOwn.terms[].upfrontPaymentDisplay | string | Upfront amount ready to show. |
rentToOwn.terms[].securityDeposit | number | Security-deposit part of the upfront amount (USD). |
rentToOwn.terms[].customerReserveAccount | number | Customer reserve account amount (USD). |
rentToOwn.terms[].deliveryFee | number | Delivery fee (USD). |
rentToOwn.terms[].taxIncluded | boolean | True when sales tax (from the ZIP) is included in the payments. |
rentToOwn.overMax | boolean | True when the price is over the rent-to-own maximum. |
rentToOwn.overMaxText | string or null | Customer-ready note to show beside the rent-to-own payments when `overMax` is true; otherwise null. |
rentToOwn.notes | list of string | Notes to show with rent-to-own. |
rentToOwn.applyUrl | string | SmartPay's own application page (reference only). |
rentToOwn.applyLink | string | Apply link (counts the click anonymously, then redirects). |
rentToOwn.applyOpensNewTab | boolean | Open `applyLink` in a new tab when true. |
rentToOwn.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
rentToOwn.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
rentToOwn.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
rentToOwn.reason | string or null | Why unavailable, as a code — e.g. `state`, `zip_not_supported`, `amount_below_minimum`, `quote_unavailable`. Null when available. |
rentToOwn.reasonText | string or null | Why unavailable, in customer-ready words. Null when available. |
rentToOwn.quoteError | string | Present only when the live rent-to-own quote failed (`reason` = `quote_unavailable`); short technical code, not for customers. |
disclosures | object | Disclosure text for the page, read live from the estimator. |
disclosures.source | string | Where the disclosure text was copied from. |
disclosures.forThisWidget | list of blocks | The disclosures your page must show, in this order. Copied word-for-word from the estimator and updated automatically — never edit or retype them. |
disclosures.forThisWidget[].type | string | Block type. |
disclosures.forThisWidget[].id | string or null | Anchor id of the block on the estimator page (e.g. `disc-credit`), or null. |
disclosures.forThisWidget[].title | string or null | Optional title (plain text), or null. |
disclosures.forThisWidget[].titleHtml | string or null | Optional title as sanitized HTML, or null. |
disclosures.forThisWidget[].paragraphs | list of object | Paragraphs to show, in order. |
disclosures.forThisWidget[].paragraphs[].text | string | Plain-text paragraph, word-for-word from the estimator page. |
disclosures.forThisWidget[].paragraphs[].html | string | Same paragraph as sanitized HTML (only `<strong>`, `<b>`, `<em>`, `<sup>` and entities). Prefer this to keep the bold text and superscript markers. |
disclosures.forThisWidget[].text | string | Heading text. |
disclosures.all | list of blocks | The estimator's complete disclosure footer (reference only). |
disclosures.footnotes | list of object | Every footnote marker and which disclosure explains it. |
disclosures.footnotes[].marker | string | Footnote marker as a plain character: `1`, `*`, `2`, `3`, `†` … |
disclosures.footnotes[].display | string | How the marker is printed: `¹`, `*`, `²`, `³`, `†` … |
disclosures.footnotes[].disclosureId | string | Id of the disclosure block that explains this marker. |
disclosures.footnotes[].title | string or null | Title of that disclosure block, or null when it has none. |
disclosures.footnotes[].appliesToThisWidget | boolean | True when the explaining block is part of `forThisWidget` (so it will be on your page). |
disclosures.footnotes[].note | string | Extra explanation. Present only on the `†` (interest-only) marker, which has no block of its own — it is explained inside the `disc-payments` section and in each term's `paymentNote`. |
disclosures.notALender | string | The "not a lender" statement on its own, for tight layouts. |
disclosures.representativeExample | string | The representative-example sentence on its own. |
disclosures.rentToOwnStructures | string | Which structures do not qualify for rent-to-own. |
displayRules | list of string | The display rules, in plain English. Please follow them. |
simulated | string | Echo of the `simulate` value, present only when one was sent (testing only). |
| Field (GET /options response) | Type | What it means |
|---|---|---|
ok | boolean | Always `true` on a successful response. |
apiVersion | string | API version (a date). |
brand | string | Brand slug. |
brandName | string | Brand display name. |
rulesFrom | object | Where and when the API read the rules it used for this response. |
rulesFrom.estimator | string | The published estimator page the rules were read from. |
rulesFrom.estimatorVersion | string | Short hash of the estimator version the rules came from. Changes whenever the estimator page changes. |
rulesFrom.readAt | string | When the rules were read from the estimator (UTC, ISO 8601). |
rulesFrom.source | string | How the rules were obtained for this response, e.g. `live` (just read from the estimator page) or `cache` (a recent read is being reused). |
questions | object | The two customer questions. |
questions.creditScore | object | One customer question, ready to render as a `<select>`. |
questions.creditScore.field | string | Name of the /estimate input this question fills. |
questions.creditScore.label | string | Question text. |
questions.creditScore.placeholder | string | Text for the empty first dropdown option. |
questions.creditScore.helpText | string | Help text to show under the question. |
questions.creditScore.options | list of object | Dropdown choices, in display order. Values are read live from the estimator — do not hard-code them. |
questions.creditScore.options[].value | string | Send this value back to /estimate. |
questions.creditScore.options[].label | string | Show this text in the dropdown. |
questions.ownProperty | object | One customer question, ready to render as a `<select>`. |
questions.ownProperty.field | string | Name of the /estimate input this question fills. |
questions.ownProperty.label | string | Question text. |
questions.ownProperty.placeholder | string | Text for the empty first dropdown option. |
questions.ownProperty.helpText | string | Help text to show under the question. |
questions.ownProperty.options | list of object | Dropdown choices, in display order. Values are read live from the estimator — do not hard-code them. |
questions.ownProperty.options[].value | string | Send this value back to /estimate. |
questions.ownProperty.options[].label | string | Show this text in the dropdown. |
inputs | object | Plain-English description of each /estimate input. |
inputs.zip | string | |
inputs.price | string | |
inputs.creditScore | string | |
inputs.ownProperty | string | |
lenders | object | Program limits per lender key: `upgrade` (Upgrade loan), `thrive` (Thrive Financial Building Loan), `rto` (SmartPay rent-to-own). |
lenders.upgrade | object | A lender program's limits, as read live from the estimator. |
lenders.upgrade.lender | string | Lender display name — show it only at the Apply step. |
lenders.upgrade.product | string | Product name. |
lenders.upgrade.minCreditScore | integer | Lowest credit-score value accepted (0 = no credit check). |
lenders.upgrade.minAmount | number | Smallest amount (USD) this program finances. |
lenders.upgrade.maxAmount | number | Largest amount (USD) this program finances. Higher prices get payments for this amount plus an `overMaxText`. |
lenders.upgrade.requiresPropertyOwnership | boolean | True when the customer (or their business) must own the property. |
lenders.upgrade.notOfferedInStates | list of string | Two-letter states where the program is not offered. |
lenders.upgrade.comingSoon | boolean | True when the program is announced but not yet open. |
lenders.upgrade.applyUrl | string | The lender's own application page. For reference — point buttons at the estimate's `applyLink` instead. |
lenders.upgrade.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
lenders.upgrade.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
lenders.upgrade.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
lenders.thrive | object | A lender program's limits, as read live from the estimator. |
lenders.thrive.lender | string | Lender display name — show it only at the Apply step. |
lenders.thrive.product | string | Product name. |
lenders.thrive.minCreditScore | integer | Lowest credit-score value accepted (0 = no credit check). |
lenders.thrive.minAmount | number | Smallest amount (USD) this program finances. |
lenders.thrive.maxAmount | number | Largest amount (USD) this program finances. Higher prices get payments for this amount plus an `overMaxText`. |
lenders.thrive.requiresPropertyOwnership | boolean | True when the customer (or their business) must own the property. |
lenders.thrive.notOfferedInStates | list of string | Two-letter states where the program is not offered. |
lenders.thrive.comingSoon | boolean | True when the program is announced but not yet open. |
lenders.thrive.applyUrl | string | The lender's own application page. For reference — point buttons at the estimate's `applyLink` instead. |
lenders.thrive.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
lenders.thrive.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
lenders.thrive.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
lenders.rto | object | A lender program's limits, as read live from the estimator. |
lenders.rto.lender | string | Lender display name — show it only at the Apply step. |
lenders.rto.product | string | Product name. |
lenders.rto.minCreditScore | integer | Lowest credit-score value accepted (0 = no credit check). |
lenders.rto.minAmount | number | Smallest amount (USD) this program finances. |
lenders.rto.maxAmount | number | Largest amount (USD) this program finances. Higher prices get payments for this amount plus an `overMaxText`. |
lenders.rto.requiresPropertyOwnership | boolean | True when the customer (or their business) must own the property. |
lenders.rto.notOfferedInStates | list of string | Two-letter states where the program is not offered. |
lenders.rto.comingSoon | boolean | True when the program is announced but not yet open. |
lenders.rto.applyUrl | string | The lender's own application page. For reference — point buttons at the estimate's `applyLink` instead. |
lenders.rto.applyHint | object | The small print the estimator shows under this lender's Apply button. Show it next to your Apply button. |
lenders.rto.applyHint.text | string | Plain-text small print (footnote markers printed as ¹ etc.). |
lenders.rto.applyHint.html | string | Same text as HTML. Sanitized server-side: only `<strong>`, `<b>`, `<em>`, `<sup>` tags and HTML entities, so it is safe to insert as HTML. |
disclosures | object | Disclosure text for the page, read live from the estimator. |
disclosures.source | string | Where the disclosure text was copied from. |
disclosures.forThisWidget | list of blocks | The disclosures your page must show, in this order. Copied word-for-word from the estimator and updated automatically — never edit or retype them. |
disclosures.forThisWidget[].type | string | Block type. |
disclosures.forThisWidget[].id | string or null | Anchor id of the block on the estimator page (e.g. `disc-credit`), or null. |
disclosures.forThisWidget[].title | string or null | Optional title (plain text), or null. |
disclosures.forThisWidget[].titleHtml | string or null | Optional title as sanitized HTML, or null. |
disclosures.forThisWidget[].paragraphs | list of object | Paragraphs to show, in order. |
disclosures.forThisWidget[].paragraphs[].text | string | Plain-text paragraph, word-for-word from the estimator page. |
disclosures.forThisWidget[].paragraphs[].html | string | Same paragraph as sanitized HTML (only `<strong>`, `<b>`, `<em>`, `<sup>` and entities). Prefer this to keep the bold text and superscript markers. |
disclosures.forThisWidget[].text | string | Heading text. |
disclosures.all | list of blocks | The estimator's complete disclosure footer (reference only). |
disclosures.footnotes | list of object | Every footnote marker and which disclosure explains it. |
disclosures.footnotes[].marker | string | Footnote marker as a plain character: `1`, `*`, `2`, `3`, `†` … |
disclosures.footnotes[].display | string | How the marker is printed: `¹`, `*`, `²`, `³`, `†` … |
disclosures.footnotes[].disclosureId | string | Id of the disclosure block that explains this marker. |
disclosures.footnotes[].title | string or null | Title of that disclosure block, or null when it has none. |
disclosures.footnotes[].appliesToThisWidget | boolean | True when the explaining block is part of `forThisWidget` (so it will be on your page). |
disclosures.footnotes[].note | string | Extra explanation. Present only on the `†` (interest-only) marker, which has no block of its own — it is explained inside the `disc-payments` section and in each term's `paymentNote`. |
disclosures.notALender | string | The "not a lender" statement on its own, for tight layouts. |
disclosures.representativeExample | string | The representative-example sentence on its own. |
disclosures.rentToOwnStructures | string | Which structures do not qualify for rent-to-own. |
displayRules | list of string | The display rules, in plain English. Please follow them. |
Questions
Tim Brazil, Lending Manager. Rates and rules are maintained on our side. When a lender changes terms, our estimator is updated, and this API and your widget pick up the change automatically.